home *** CD-ROM | disk | FTP | other *** search
- /* example.c - an example of using libpng */
-
- /* this is an example of how to use libpng to read and write
- png files. The file libpng.txt is much more verbose then
- this. If you have not read it, do so first. This was
- designed to be a starting point of an implementation.
- This is not officially part of libpng, and therefore
- does not require a copyright notice.
- */
-
- #include <png.h>
-
- /* check to see if a file is a png file using png_check_sig() */
- int check_png(char *file_name)
- {
- FILE *fp;
- char buf[8];
- int ret;
-
- fp = fopen(file_name, "rb");
- if (!fp)
- return 0;
- ret = fread(buf, 1, 8, fp);
- fclose(fp);
-
- if (ret != 8)
- return 0;
-
- ret = png_check_sig(buf, 8);
-
- return (ret);
- }
-
- /* read a png file. You may want to return an error code if the read
- fails (depending upon the failure). */
- void read_png(char *file_name)
- {
- FILE *fp;
- png_struct *png_ptr;
- png_info *info_ptr;
-
- /* open the file */
- fp = fopen(file_name, "rb");
- if (!fp)
- return;
-
- /* allocate the necessary structures */
- png_ptr = malloc(sizeof (png_struct));
- if (!png_ptr)
- {
- fclose(fp);
- return;
- }
-
- info_ptr = malloc(sizeof (png_info));
- if (!info_ptr)
- {
- fclose(fp);
- free(png_ptr);
- return;
- }
-
- /* set error handling */
- if (setjmp(png_ptr->jmpbuf))
- {
- png_read_destroy(png_ptr, info_ptr, (png_info *)0);
- fclose(fp);
- free(png_ptr);
- free(info_ptr);
- /* If we get here, we had a problem reading the file */
- return;
- }
-
- /* initialize the structures, info first for error handling */
- png_info_init(info_ptr);
- png_read_init(png_ptr);
-
- /* set up the input control */
- png_init_io(png_ptr, fp);
-
- /* read the file information */
- png_read_info(png_ptr, info_ptr);
-
- /* allocate the memory to hold the image using the fields
- of png_info. */
-
- /* set up the transformations you want. Note that these are
- all optional. Only call them if you want them */
-
- /* expand paletted colors into true rgb */
- if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
- info_ptr->bit_depth < 8)
- png_set_expand(png_ptr);
-
- /* expand grayscale images to the full 8 bits */
- if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
- info_ptr->bit_depth < 8)
- png_set_expand(png_ptr);
-
- /* expand images with transparency to full alpha channels */
- if (info_ptr->valid & PNG_INFO_tRNS)
- png_set_expand(png_ptr);
-
- /* Set the background color to draw transparent and alpha
- images over */
- png_color_16 my_background;
-
- if (info_ptr->valid & PNG_INFO_bKGD)
- png_set_background(png_ptr, &(info_ptr->background),
- PNG_GAMMA_FILE, 1, 1.0);
- else
- png_set_background(png_ptr, &my_background,
- PNG_GAMMA_SCREEN, 0, 1.0);
-
- /* tell libpng to handle the gamma conversion for you */
- if (info_ptr->valid & PNG_INFO_gAMA)
- png_set_gamma(png_ptr, screen_gamma, info_ptr->gamma);
- else
- png_set_gamma(png_ptr, screen_gamma, 0.45);
-
- /* tell libpng to strip 16 bit depth files down to 8 bits */
- if (info_ptr->bit_depth == 16)
- png_set_strip_16(png_ptr);
-
- /* dither rgb files down to 8 bit palettes & reduce palettes
- to the number of colors available on your screen */
- if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
- {
- if (info_ptr->valid & PNG_INFO_PLTE)
- png_set_dither(png_ptr, info_ptr->palette,
- info_ptr->num_palette, max_screen_colors,
- info_ptr->histogram);
- else
- {
- png_color std_color_cube[MAX_SCREEN_COLORS] =
- {/* ... colors ... */};
-
- png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS,
- MAX_SCREEN_COLORS, NULL);
- }
- }
-
- /* invert monocrome files */
- if (info_ptr->bit_depth == 1 &&
- info_ptr->color_type == PNG_COLOR_GRAY)
- png_set_invert(png_ptr);
-
- /* shift the pixels down to their true bit depth */
- if (info_ptr->valid & PNG_INFO_sBIT &&
- info_ptr->bit_depth > info_ptr->sig_bit)
- png_set_shift(png_ptr, &(info_ptr->sig_bit));
-
- /* pack pixels into bytes */
- if (info_ptr->bit_depth < 8)
- png_set_packing(png_ptr);
-
- /* flip the rgb pixels to bgr */
- if (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
- info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- png_set_bgr(png_ptr);
-
- /* swap bytes of 16 bit files to least significant bit first */
- if (info_ptr->bit_depth == 16)
- png_set_swap(png_ptr);
-
- /* add a filler byte to store rgb files as rgbx */
- if (info_ptr->bit_depth == 8 &&
- info_ptr->color_type == PNG_COLOR_TYPE_RGB)
- png_set_rgbx(png_ptr);
-
- /* optional call to update palette with transformations */
- png_start_read_image(png_ptr);
-
- /* the easiest way to read the image */
- void *row_pointers[height];
- png_read_image(png_ptr, row_pointers);
-
- /* the other way to read images - deal with interlacing */
-
- /* turn on interlace handling */
- if (info_ptr->interlace_type)
- number_passes = png_set_interlace_handling(png_ptr);
- else
- number_passes = 1;
-
- for (pass = 0; pass < number_passes; pass++)
- {
- /* Read the image using the "sparkle" effect. */
- png_read_rows(png_ptr, row_pointers, NULL, number_of_rows);
-
- /* If you are only reading on row at a time, this works */
- for (y = 0; y < height; y++)
- {
- char *row_pointers = row[y];
- png_read_rows(png_ptr, &row_pointers, NULL, 1);
- }
-
- /* to get the rectangle effect, use the third parameter */
- png_read_rows(png_ptr, NULL, row_pointers, number_of_rows);
-
- /* if you want to display the image after every pass, do
- so here */
- }
-
- /* read the rest of the file, getting any additional chunks
- in info_ptr */
- png_read_end(png_ptr, info_ptr);
-
- /* clean up after the read, and free any memory allocated */
- png_read_destroy(png_ptr, info_ptr, (png_info *)0);
-
- /* free the structures */
- free(png_ptr);
- free(info_ptr);
-
- /* close the file */
- fclose(fp);
-
- /* that's it */
- return;
- }
-
- /* write a png file */
- void write_png(char *file_name, ... other image information ...)
- {
- FILE *fp;
- png_struct *png_ptr;
- png_info *info_ptr;
-
- /* open the file */
- fp = fopen(file_name, "wb");
- if (!fp)
- return;
-
- /* allocate the necessary structures */
- png_ptr = malloc(sizeof (png_struct));
- if (!png_ptr)
- {
- fclose(fp);
- return;
- }
-
- info_ptr = malloc(sizeof (png_info));
- if (!info_ptr)
- {
- fclose(fp);
- free(png_ptr);
- return;
- }
-
- /* set error handling */
- if (setjmp(png_ptr->jmpbuf))
- {
- png_write_destroy(png_ptr);
- fclose(fp);
- free(png_ptr);
- free(info_ptr);
- /* If we get here, we had a problem reading the file */
- return;
- }
-
- /* initialize the structures */
- png_info_init(info_ptr);
- png_write_init(png_ptr);
-
- /* set up the output control */
- png_init_io(png_ptr, fp);
-
- /* set the file information here */
- info_ptr->width = ;
- info_ptr->height = ;
- etc.
-
- /* set the palette if there is one */
- info_ptr->valid |= PNG_INFO_PLTE;
- info_ptr->palette = malloc(256 * sizeof (png_color));
- info_ptr->num_palette = 256;
- ... set palette colors ...
-
- /* optional significant bit chunk */
- info_ptr->valid |= PNG_INFO_sBIT;
- info_ptr->sig_bit = true_bit_depth;
-
- /* optional gamma chunk */
- info_ptr->valid |= PNG_INFO_gAMA;
- info_ptr->gamma = gamma;
-
- /* other optional chunks */
-
- /* write the file information */
- png_write_info(png_ptr, info_ptr);
-
- /* set up the transformations you want. Note that these are
- all optional. Only call them if you want them */
-
- /* invert monocrome pixels */
- png_set_invert(png_ptr);
-
- /* shift the pixels up to a legal bit depth and fill in
- as appropriate to correctly scale the image */
- png_set_shift(png_ptr, &(info_ptr->sig_bit));
-
- /* pack pixels into bytes */
- png_set_packing(png_ptr);
-
- /* flip bgr pixels to rgb */
- png_set_bgr(png_ptr);
-
- /* swap bytes of 16 bit files to most significant bit first */
- png_set_swap(png_ptr);
-
- /* get rid of filler bytes, pack rgb into 3 bytes */
- png_set_rgbx(png_ptr);
-
- /* the easiest way to write the image */
- void *row_pointers[height];
- png_write_image(png_ptr, row_pointers);
-
- /* the other way to write the image - deal with interlacing */
-
- /* turn on interlace handling */
- if (interlacing)
- number_passes = png_set_interlace_handling(png_ptr);
- else
- number_passes = 1;
-
- for (pass = 0; pass < number_passes; pass++)
- {
- /* Write a few rows at a time. */
- png_write_rows(png_ptr, row_pointers, number_of_rows);
-
- /* If you are only writing one row at a time, this works */
- for (y = 0; y < height; y++)
- {
- char *row_pointers = row[y];
- png_write_rows(png_ptr, &row_pointers, 1);
- }
- }
-
- /* write the rest of the file */
- png_write_end(png_ptr, info_ptr);
-
- /* clean up after the write, and free any memory allocated */
- png_write_destroy(png_ptr);
-
- /* if you malloced the palette, free it here */
- if (info_ptr->palette)
- free(info_ptr->palette);
-
- /* free the structures */
- free(png_ptr);
- free(info_ptr);
-
- /* close the file */
- fclose(fp);
-
- /* that's it */
- return;
- }
-
-